<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Common\Middleware;

use App\Common\Repositories\System\CustomerAdminRepository;
use App\Exception\AppException;
use Exception;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\SignatureInvalidException;
use Hyperf\HttpServer\Contract\RequestInterface as Request;
use Hyperf\HttpServer\Contract\ResponseInterface as Response;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Throwable;
use xsl\enums\Code;
use xsl\enums\Status;
use xsl\services\JwtTokenService;

class AdminMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var Response
     */
    protected $response;

    protected $request;

    public function __construct(ContainerInterface $container, Response $response, Request $request)
    {
        $this->container = $container;
        $this->response = $response;
        $this->request = $request;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        try {
            $Authorization = $request->getHeader('Authorization');
            $token = trim($Authorization[0]);
            if (strpos($token, 'Bearer') === 0) {
                $token = trim(substr($token, 6));
            }
            if (! $token) {
                throw new AppException('请登录', Code::LOGIN_EXPIRED);
            }
            /**
             * @var CustomerAdminRepository $repository
             */
            $repository = \Hyperf\Support\make(CustomerAdminRepository::class);
            $service = new JwtTokenService();
            try {
                $payload = $service->parseToken($token);
            } catch (BeforeValidException|ExpiredException|SignatureInvalidException $e) {
                //过期等操作
                $repository->checkToken($token);
                $payload = $service->decode($token);
            } catch (Throwable $e) {// Token 过期
                throw new AppException($e->getMessage());
            }

            if ($payload->jti[1] != 'admin') {
                throw new AppException('无效的 token', Code::LOGIN_EXPIRED);
            }
            $admin = $repository->get($payload->jti[0]);
            if (! $admin) {
                throw new AppException('账号不存在', Code::LOST_LOGIN);
            }
            if ($admin->status != Status::ENABLE) {
                throw new AppException('账号已被禁用', Code::LOST_LOGIN);
            }

            $this->request->macro('isLogin', function () {
                return true;
            });
            $this->request->macro('tokenInfo', function () use (&$payload) {
                return $payload;
            });
            $this->request->macro('token', function () use (&$token) {
                return $token;
            });
            $this->request->macro('adminId', function () use (&$admin) {
                return $admin->id;
            });
            $this->request->macro('adminInfo', function () use (&$admin) {
                return $admin;
            });
        } catch (AppException|Exception $e) {
            return $this->response->json(
                [
                    'code' => $e->getCode(),
                    'msg' => $e->getMessage(),
                ]
            );
        }
        return $handler->handle($request);
    }
}
